using System;
using System.ComponentModel;
using System.Data;
using System.Xml;
using System.Text;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Net;

namespace Common
{
    /// <summary>
    /// Provides global static methods and properties
    /// </summary>
    public static class Controller
    {
        #region Variables

        // using for encrypt & decrypt data
        private const string Key = "x2";
        private static string _computerName;

        #endregion

        #region Properties

        public static bool DesignMode
        {
            get
            {
                return LicenseManager.UsageMode == LicenseUsageMode.Designtime;
            }
        }

        public static string MainTitle
        {
            get { return ReadString("MainTitle"); }
        }
        
        public static string ApplicationPath
        {
            get { return StartupPath; }
        }

        /// <summary>
        /// The path to executive file.
        /// </summary>
        /// <author>Han added on September, 15, 2007</author>
        public static string StartupPath
        {
            get
            {
                string startupPath = DesignMode
                                         ? string.Concat(Environment.GetFolderPath(Environment.SpecialFolder.
                                                                                       ApplicationData), "\\DIV")
                                         : System.Windows.Forms.Application.StartupPath;
                return startupPath;
            }
        }

        /// <summary>
        /// Get the path of Report directory.
        /// The path to current report folder with "\" included
        /// </summary>
        /// <author>Han added on September, 15, 2007</author>
        public static string CurrentReportPath
        {
            get
            {
                //return StartupPath + @"Report\";
                return ApplicationPath + @"\\Report\";
            }
        }

        /// <summary>
        /// Get the path of service report directory.
        /// The path to current service report folder with "\" included
        /// </summary>
        public static string CurrentServiceReportPath
        {
            get { return StartupPath + @"Report\PrintService\"; }
        }

        public static bool ApplicationExiting { get; set; }

        /// <summary>
        /// Gets the name of computer
        /// </summary>
        public static string ComputerName
        {
            get { return _computerName ?? (_computerName = Dns.GetHostName()); }
        }

        #endregion

        #region Private methods

        private static XmlDocument LoadConfigDocument()
        {
            var doc = new XmlDocument();
            doc.Load(GetConfigFilePath());
            return doc;
        }

        private static string GetConfigFilePath ()
        {
#if DEBUG
            var configFile = string.Concat(ApplicationPath, @"\TDTP.exe.config");
#else			
			fileName = Environment.GetCommandLineArgs()[0];
			fileName = fileName.Substring(fileName.LastIndexOf('\\')+1)+ ".Config";
			configFile = string.Concat(Controller.ApplicationPath, "\\", fileName);
#endif
            return configFile;
        }

        #endregion

        #region Public methods

        public static string ReadString (string key)
        {
            //			if (_designMode)
            //			{
            //				return string.Empty;
            //			}
            // load config document for current assembly
            XmlDocument doc = LoadConfigDocument();

            // retrieve appSettings node
            XmlNode node = doc.SelectSingleNode("//appParams");

            // select the 'add' element that contains the key
            var elemt = (XmlElement) node.SelectSingleNode(string.Format("//add[@key='{0}']", key));

            if(elemt != null && elemt.Attributes["value"] != null)
            {
                return elemt.Attributes["value"].Value;
            }
            return null;
        }

        public static void WriteString (string key, string value)
        {
            // load config document for current assembly
            var doc = LoadConfigDocument();

            // retrieve appSettings node
            var node = doc.SelectSingleNode("//appParams");

            // select the 'add' element that contains the key
            var elem = (XmlElement) node.SelectSingleNode(string.Format("//add[@key='{0}']", key));

            if(elem != null)
            {
                // add value for key
                elem.SetAttribute("value", value);
            }
            else
            {
                // key was not found so create the 'add' element 
                // and set it's key/value attributes 
                elem = doc.CreateElement("add");
                elem.SetAttribute("key", key);
                elem.SetAttribute("value", value);
                node.AppendChild(elem);
            }
            doc.Save(GetConfigFilePath());
        }

        public static void RemoveString (string key)
        {
            // load config document for current assembly
            var doc = LoadConfigDocument();

            // retrieve appSettings node
            var node = doc.SelectSingleNode("//appParams");

            // remove 'add' element with coresponding key
            node.RemoveChild(node.SelectSingleNode(string.Format("//add[@key='{0}']", key)));
            doc.Save(GetConfigFilePath());
        }

        /// <summary>
        /// Convert Enum to DataTable
        /// Mai Tran started on Aug 24, 2007
        /// </summary>
        /// <param name="enumObject">Which enum want to convert</param>
        /// <param name="keyField">first column in datatable</param>
        /// <param name="valueField">second column in datable</param>
        /// <returns></returns>
        public static DataTable EnumToDataTable (Type enumObject, string keyField, string valueField)
        {
            var dt = new DataTable();
            var colKeyField = new DataColumn(keyField, typeof(int));
            var colValueField = new DataColumn(valueField, typeof(string));

            dt.Columns.Add(colKeyField);
            dt.Columns.Add(colValueField);

            foreach(object iEnumItem in Enum.GetValues(enumObject))
            {
                DataRow dr = dt.NewRow();
                dr[keyField] = Convert.ToInt32(iEnumItem);
                dr[valueField] = iEnumItem.ToString();
                dt.Rows.Add(dr);
            }
            return dt;
        }

        public static string Encrypt (string toEncrypt)
        {
            if(toEncrypt == null)
            {
                toEncrypt = string.Empty;
            }

            try
            {
                byte[] toEncryptArray = Encoding.UTF8.GetBytes(toEncrypt);

                var hashmd5 = new MD5CryptoServiceProvider();
                byte[] keyArray = hashmd5.ComputeHash(Encoding.UTF8.GetBytes(Key));

                var tdes = new TripleDESCryptoServiceProvider
                                                          {
                                                              Key = keyArray,
                                                              Mode = CipherMode.ECB,
                                                              Padding = PaddingMode.PKCS7
                                                          };

                var cTransform = tdes.CreateEncryptor();
                byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

                return Convert.ToBase64String(resultArray, 0, resultArray.Length);
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }

        public static string Decrypt (string toDecrypt)
        {
            try
            {
                byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);

                var hashmd5 = new MD5CryptoServiceProvider();
                byte[] keyArray = hashmd5.ComputeHash(Encoding.UTF8.GetBytes(Key));

                var tdes = new TripleDESCryptoServiceProvider
                                                          {
                                                              Key = keyArray,
                                                              Mode = CipherMode.ECB,
                                                              Padding = PaddingMode.PKCS7
                                                          };

                ICryptoTransform cTransform = tdes.CreateDecryptor();
                byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

                return Encoding.UTF8.GetString(resultArray);
            }
            catch(Exception ex)
            {
                throw ex;
            }
        }
        
        public static string DateString (bool includeTime)
        {
            return DateTime.Now.ToString(includeTime
                                             ? "yyyyMMdd-hhmmss"
                                             : "yyyyMMdd");
        }

        public static string ModuleType
        {
            get { return ReadString("ModuleType"); }
        }

        /// <summary>
        /// Pre-process Sql string
        /// </summary>
        /// <param name="stringToProcess">string to process</param>
        /// <returns></returns>
        public static string PreProcessSqlString (string stringToProcess)
        {
            string returnString = stringToProcess ?? string.Empty;
            returnString = returnString.Replace("'", "''");
            return returnString;
        }

        /// <summary>
        /// Check email address Lieu Hoang
        /// </summary>
        /// <param name="sEmail"></param>
        /// <returns></returns>
        public static bool IsValidEmailAddress (string sEmail)
        {
            return sEmail != null &&
                   Regex.IsMatch(sEmail, @"^[-a-zA-Z0-9][-.a-zA-Z0-9]*@[-.a-zA-Z0-9]+(\.[-.a-zA-Z0-9]+)*\.(
					com|edu|info|gov|int|mil|net|org|biz|
					name|museum|coop|aero|pro|[a-zA-Z]{2})$",
                                 RegexOptions.IgnorePatternWhitespace);
        }

        #endregion
    }
}
